// https://www.cnblogs.com/CCxi/p/9445545.html

// 数据类型
console.log(typeof true); // "boolean"
Object.prototype.toString.call(true);

// Number : true -->1 false -->0
console.log(Number(true));
console.log(Number(false));

// Boolean : 把其他数据类型转换布尔值；
console.log(Boolean(12)); //true
console.log(Boolean(10)); //true
console.log(Boolean(0)); //false
console.log(Boolean('{}')); //true
console.log(Boolean('12px')); //true
console.log(Boolean([])); //true
console.log(Boolean({})); //true
console.log(Boolean(null)); //false
console.log(Boolean(undefined)); //false
console.log(Boolean(NaN)); //false
console.log(Boolean(/\d/)); //true

// 逻辑运算符： ||： 或 &&： 并且； !取反

// 1.放在if条件中；
// || : 只要其中有一个为true，整体结果是true；
// && : 只要有一个是false，整体结果是false；
if ('' || 0) {
  console.log(100);
}
if (99 && 0) {
  console.log(0);
}

// 2.赋值作用；
// 如果前面这个值转布尔是true，直接取前面这个值；如果转布尔是false，直接取后面的那个值；
var abc = '12px' || undefined;
console.log(abc); //12px
// 如果前面转布尔是true，直接取后面那个值；如果转布尔是false，直接前面的值；
var bcd = null && 17;
console.log(bcd); //null

// 数据类型之间的比较： true /false;
// !:取反；首先会把后面的值转换成布尔值，然后在取反；
console.log(!1); //true
// !!:直接把当前转换布尔值
console.log(!!''); //false

// null和undefined
// null 和 undefined都代表没有；
// typeof null –> “object”; 空对象指针；
// 区别： null 表示现在没有，但是以后可能会有；
// undefined ：现在没有，以后也不能有；

// 常见的null的情况
// 1.通过ID获取元素，如果ID名字不存在，那么返回null；
// 2.通过正则进行捕获时，如果没有捕获到内容，那么结果是null；
// 3.在清空对象，销毁堆内存时，给对象赋值时，赋值为null；

// 常见的undefined的情况
// 当获取对象属性名对应的属性值时如果属性名不存在，那么返回值是undefined；
// 函数的形参如果没有实参赋值，在函数中默认存储undefined
// 如果函数没有return，那么函数的返回值是undefined；
// 如果变量只声明，没有赋值，那么默认存储也是undefined；
var gg = document.getElementById('ab');
console.log(gg); //null
var obj = { a: 1 };
console.log(obj.b); //undefined
var c;
console.log(c); //undefined
var a;
console.log(a); //undefined

// 对象
// 1、引用数据类型，存储到堆内存中；
// 对象： 由键值对组成；键值对由属性值和属性名组成；键值对用逗号隔开
// 属性名和属性值用冒号隔开； 属性名是字符串类型，属性值是数据类型的一种；
var obj = { a: [] };
var o = { a: 2 };

// 没有length属性；没有索引；
console.log(obj[0]);
var a = 1;

// 对象名实际存储的是一个空间地址；
console.log(obj);
var a = {};
var b = {};

// 在JS中遇到{}、[] 都会开辟新的空间地址；
var a = (b = {});
var a = (b = c = d = 10);
d = 9;
console.log(a); // 10;
var a = (b = c = { a: 1 });
c = {};
c.a = 2;
console.log(a); //{a:1}
console.log(c); // {a:2}

// 对象的增删改查
var obj = { num: 1, str: 'abc', 6: 10 };
// 1.新增键值对：
// 对象名.属性名=属性值
obj.a = 100;
console.log(obj);
// 对象名['属性名'] = 属性值；
obj['a'] = 100;
obj['12'] = 13;
console.log(obj);
// 如果属性名是数字的话，会按照数字从小到大顺序显示；

//2.查询: 如果属性名不存在，那么获取的属性值是undefined；
var v = obj.num;
var b = obj['num'];
console.log(v); // 1
var c = 'num';
var d = obj[c];
var obj = { num: 1, str: 'abc', 6: 10 };

// 3.修改: 属性没有就是新增，有就是修改；
obj.num = 10;
obj.a = '1';
obj['num'] = 100;
console.log(obj);

// 4.删除
// 假删除;
// 真删除
obj.num = null;
// delete delete 对象名.属性名
delete obj.num;
console.log(obj);
var a = obj.num;

// in : 判断当前属性名在对象中是否存在；如果存在返回true，不存在返回false；
// "属性名" in 对象名
console.log('num1' in obj);

// 数组
// 数组：由数组成员组成，数组成员之间用逗号隔开；
// 有索引，有length；
var ary = [12, 12, 47, 128, 'uu', {}, true];
// 数组成员都有一个与之对应的索引；从0开始；
// 有length属性，代表数组成员的个数；
console.log(ary[4]);
console.log(ary.length); // 7
console.log(ary[ary.length - 1]);
var a = [];
var b = [];
ary[7] = 18;
console.log(ary);

// 检测
// typeof :返回一个字符串；字符串中内容代表当前的数据类型；
// typeof NaN -->"number"
// typeof null --> "object" 空对象指针
// 局限性： 只能区分基本数据类型；但是不能细分对象数据类型下的对象，数组，正则；
// typeof true–>”boolean”
// typeof undefined –>”undefined”
// instanceof : 检测当前实例是否属于某个类的方法；
var pbj = { a: 1 };
var aru = [];
console.log(pbj instanceof Object);
console.log(pbj instanceof Array);
console.log(aru instanceof Array);
// constructor : 检测当前实例的构造函数
// Object.prototype.toString.call([]); 最准确的方式；

// 数据类型之间比较的规律
// = : 赋值；
var a = 19;
var a = 20;
var obj = {};
obj.a = 100;

// == : 比较； 返回一个布尔值；
console.log(1 == '1'); // true
console.log(1 == true); // true
console.log([] == '1'); // false
console.log({} == []); // false
console.log(NaN == NaN); // false
console.log(null == null); // true
console.log(null == undefined); // true
console.log(null === undefined); // false
// *****NaN 和自己都不相等*****

// 数据类型比较的规律
// 对象==对象： 比较的是空间地址
// 对象==字符串 对象默认调用toString方法，先转字符串，然后再进行比较
// 对象==布尔： 对象先转字符串，再转数字；布尔直接转数字；
// 对象== 数字 : 对象先调用toString转换成字符串，然后再转number;
// 布尔== 数字 ： 布尔转数字；
// 字符串== 数字： 字符串转数字；
// 布尔== 字符串 : 布尔转数字，字符串也转数字，然后进行比较；
// null == undefined : true;
// null 和 undefined 和其他数据类型比较都是false；
console.log({} == {}); // false
console.log({} == ''); // false
console.log({} == true); // false
console.log([] == 0); // true
console.log([] == false); // true
console.log(true == 10); //false
console.log('' == 0); //true
console.log(true == '1'); // true
console.log('1' == '1px'); //false
console.log('' == ' '); //false

// ! : 首先会把后面的值转成布尔值，然后再进行取反；
console.log([] === false); // true
console.log(![] == false); // true;
console.log(!isNaN('12px') == 0); // true;
console.log(!{} == {}); // false
({}.toString()); //"[object Object]"

// === : 绝对比较；不会进行数据类型之间的转换；只要数据类型不一样，就是false；
console.log(1 === '1'); //false
console.log({} === {}); // false
console.log([] === false); // true

// ! :后面跟等号，代表不等于；
// !== : 绝对不等于    console.log([] !== false)// true
// != : 会进行数据类型之间的比较；
